/**
 * Copyright (c) 2006 RiseSoft Co.,Ltd  
 * $Header$
 */
package net.risesoft.risebi.collection.web.admin;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.risesoft.risebi.collection.model.Application;
import net.risesoft.risebi.collection.model.RiseScheduler;
import net.risesoft.risebi.collection.model.Service;
import net.risesoft.risebi.collection.model.User;
import net.risesoft.risebi.collection.scheduler.SchedulerConstant;
import net.risesoft.risebi.collection.scheduler.SchedulerService;
import net.risesoft.risebi.collection.scheduler.job.RiseJob;
import net.risesoft.risebi.collection.service.SchedulerManager;
import net.risesoft.risebi.collection.web.BaseAction;
import net.risesoft.risebi.commons.struts2extension.Trimable;
import net.risesoft.risebi.commons.util.ExceptionUtil;
import net.risesoft.risebi.commons.util.GUID;
import net.risesoft.risebi.commons.util.JSONUtil;
import net.risesoft.risebi.commons.util.SerializableUtil;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.LazyDynaBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.quartz.JobDataMap;

import com.opensymphony.xwork2.ActionInvocation;

/**
 *
 *
 * @author <a href="mailto: chenjian@risesoft.net">陈健</a>
 * @version $Revision$
 * 
 */
@Namespace("/admin/SchedulerAction")
public class SchedulerAction extends BaseAction implements Trimable {

	private static final long serialVersionUID = 4754009543708519214L;
	
	private static Log log = LogFactory.getLog(SchedulerAction.class);
	
	private SchedulerManager schedulerManager;
	
	private SchedulerService schedulerServiceClient;
	
	public void setSchedulerServiceClient(SchedulerService schedulerServiceClient) {
		this.schedulerServiceClient = schedulerServiceClient;
	}

	public void setSchedulerManager(SchedulerManager schedulerManager) {
		this.schedulerManager = schedulerManager;
	}

	/**
	 * service/application
	 */
	private String whichType;
	
	private String detailValue;
	
	private RiseScheduler riseScheduler;

	public RiseScheduler getRiseScheduler() {
		return riseScheduler;
	}

	public void setRiseScheduler(RiseScheduler riseScheduler) {
		this.riseScheduler = riseScheduler;
	}

	public String getDetailValue() {
		return detailValue;
	}

	public void setDetailValue(String detailValue) {
		this.detailValue = detailValue;
	}

	public String getWhichType() {
		return whichType;
	}

	public void setWhichType(String whichType) {
		this.whichType = whichType;
	}

	private boolean startAtOnce;
	private String jobType;
	private String jobName;
	private String startDateTime;
	private String cronExpression;

	public String getCronExpression() {
		return cronExpression;
	}

	public void setCronExpression(String cronExpression) {
		this.cronExpression = cronExpression;
	}

	private Map<String,String> rjd;
	
	public Map<String,String> getRjd() {
		return rjd;
	}

	public void setRjd(Map<String,String> rjd) {
		this.rjd = rjd;
	}

	public String getJobType() {
		return jobType;
	}

	public void setJobType(String jobType) {
		this.jobType = jobType;
	}

	public boolean isStartAtOnce() {
		return startAtOnce;
	}

	public void setStartAtOnce(boolean startAtOnce) {
		this.startAtOnce = startAtOnce;
	}

	public String getJobName() {
		return jobName;
	}

	public void setJobName(String jobName) {
		this.jobName = jobName;
	}

	public String getStartDateTime() {
		return startDateTime;
	}

	public void setStartDateTime(String startDateTime) {
		this.startDateTime = startDateTime;
	}

	/* (non-Javadoc)
	 * @see net.risesoft.risebi.commons.struts2extension.Trimable#afterTrim(com.opensymphony.xwork2.ActionInvocation)
	 */
	public void afterTrim(ActionInvocation invocation) {
		
	}

	/* (non-Javadoc)
	 * @see net.risesoft.risebi.commons.struts2extension.Trimable#preTrim(com.opensymphony.xwork2.ActionInvocation)
	 */
	public boolean preTrim(ActionInvocation invocation) {
		return true;
	}
	
	@Action(value="list",
			results={@Result(name="success", location="/admin/scheduler/list.jsp")}
	)
	public String list() throws Exception {
		return SUCCESS;
	}
	
	@Action(value="refreshJson")
	public String refreshJson() throws Exception {
		try{
			if(whichType.equals("service")){
				Service service = this.getDefaultService();
				User user = this.getSessionUser();
				
				String serviceGuid = service.getGuid();
				String userGuid = user.getGuid();
				List<RiseScheduler> lst = schedulerManager.getServiceScheduler(serviceGuid);
				this.json = JSONUtil.getJsonString("include","guid,name,createdDate,startDate,endDate,cronExpression,status",lst);
			}else{
				User user = this.getSessionUser();
				Application application = this.getDefaultApp();
				String applicationGuid = application.getGuid();
				String userGuid = user.getGuid();
				List<RiseScheduler> lst = null;
				if(user.isServiceAdmin()){
					lst = schedulerManager.getServiceApplicationScheduler(applicationGuid);
				}else{
					lst = schedulerManager.getSelfApplicationScheduler(applicationGuid, userGuid);
				}
				
				this.json = JSONUtil.getJsonString("include","guid,name,createdDate,startDate,endDate,cronExpression,status",lst);
			}
		}catch(Exception e){
			this.json = "[]";
			log.error(ExceptionUtil.transformException(e));
		} 

		return AJAX;
	}
	
	@Action(value="addWizard1",
			results={@Result(name="addWizardService1", location="/admin/scheduler/addwizard_1_service.jsp"),
			@Result(name="addWizardApplication1", location="/admin/scheduler/addwizard_1_application.jsp")}
	)
	public String addWizard1() throws Exception {
		if(whichType.equals("service")){
			return "addWizardService1";
		}else{
			return "addWizardApplication1";
		}
	}
	
	@Action(value="editWizard1",
			results={@Result(name="editWizardService1", location="/admin/scheduler/editwizard_1_service.jsp"),
			@Result(name="editWizardApplication1", location="/admin/scheduler/editwizard_1_application.jsp")}
	)
	public String editWizard1() throws Exception {
		riseScheduler = (RiseScheduler) schedulerManager.getObject(RiseScheduler.class, node);
		
		if(whichType.equals("service")){
			return "editWizardService1";
		}else{
			return "editWizardApplication1";
		}
	}
	
	@Action(value="addWizard2",
			results={@Result(name="success", location="/admin/scheduler/${jobType}/addwizard_2_${jobType}.jsp")}
	)
	public String addWizard2() throws Exception {
		return SUCCESS;
	}
	
	@Action(value="editWizard2",
			results={@Result(name="success", location="/admin/scheduler/${jobType}/editwizard_2_${jobType}.jsp")}
	)
	public String editWizard2() throws Exception {
		riseScheduler = (RiseScheduler)schedulerManager.getObject(RiseScheduler.class,node);
		
		byte[] b = riseScheduler.getJobData();
		JobDataMap jobDataMap = (JobDataMap) SerializableUtil.unSerialize(b);
		if(rjd==null)
			rjd = new HashMap<String,String>();
		rjd.putAll(jobDataMap);
		
		return SUCCESS;
	}
	
	@Action(value="add")
	public String add() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		
		try {
			User user = this.getSessionUser();
			
			RiseJob job = new RiseJob();
			job.setJobGuid(new GUID().toString());
			job.setUserGuid(user.getGuid());
			job.setJobName(jobName);
			job.setJobGroupName(jobType+"_JOBGROUP");
			job.setTriggerGroupName(jobType+"_TRIGGERGROUP");
			job.setJobType(jobType);
			job.setRjd(rjd);
			job.setStartAtOnce(startAtOnce);
			job.setCronExpression(cronExpression);
			
			Service service = this.getDefaultService();
			if(whichType.equals("service")){
				job.setServiceGuid(service.getGuid());
			}else{
				Application application = this.getDefaultApp();
				job.setServiceGuid(service.getGuid());
				job.setApplicationGuid(application.getGuid());
			}
			
			if(!startAtOnce){
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:m:s");
				Date d = sdf.parse(startDateTime);
				job.setStartDateTime(d);
			}else{
				job.setStartDateTime(new Date());
			}
			
			schedulerServiceClient.addJob(job);
			
			ldb.set("success", true);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();	
		return AJAX;
	}
	
	@Action(value="edit")
	public String edit() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		
		try {
			User user = this.getSessionUser();
			
			RiseJob job = new RiseJob();
			job.setJobGuid(new GUID().toString());
			job.setUserGuid(user.getGuid());
			job.setJobName(jobName);
			job.setJobGroupName(jobType+"_JOBGROUP");
			job.setTriggerGroupName(jobType+"_TRIGGERGROUP");
			job.setJobType(jobType);
			job.setRjd(rjd);
			job.setStartAtOnce(startAtOnce);
			job.setCronExpression(cronExpression);
			
			Service service = this.getDefaultService();
			if(whichType.equals("service")){
				job.setServiceGuid(service.getGuid());
			}else{
				Application application = this.getDefaultApp();
				job.setServiceGuid(service.getGuid());
				job.setApplicationGuid(application.getGuid());
			}
			
			if(!startAtOnce){
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:m:s");
				Date d = sdf.parse(startDateTime);
				job.setStartDateTime(d);
			}else{
				job.setStartDateTime(new Date());
			}
			
			schedulerServiceClient.editJob(job,node);
			
			ldb.set("success", true);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();	
		return AJAX;
	}
	
	@Action(value="validateCronExpression")
	public String validateCronExpression() throws Exception {
		boolean b = schedulerServiceClient.validateCronExpression(cronExpression);
		
		LazyDynaBean ldb = new  LazyDynaBean();
		if(b){
			ldb.set("success", true);
			ldb.set("reason", "表达式正确");
		}else{
			ldb.set("success", false);
			ldb.set("reason", "表达式有错");
		}
		
		this.json = JSONObject.fromObject(ldb).toString();

		return AJAX;
	}
	
	@Action(value="stopJob")
	public String stopJob() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		try {
//			需要判断一下该任务是否已经完成
			int status = schedulerServiceClient.getJobStatus(node);
			if(status==RiseScheduler.STATUS_COMPLETED_ERROR||status==RiseScheduler.STATUS_COMPLETED_NOERROR){
				ldb.set("success", true);
				ldb.set("reason", "该任务已经完成，无法停止。\n\r请刷新一下。");
				ldb.set("needrefresh", "1");
				this.json = JSONObject.fromObject(ldb).toString();
				return AJAX;
			}
			
			schedulerServiceClient.stopJob(node);
			
			ldb.set("success", true);
			ldb.set("reason", "任务成功停止");
			ldb.set("needrefresh", "0");
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		
		return AJAX;
	}
	
	@Action(value="startJob")
	public String startJob() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		try {
			int status = schedulerServiceClient.startJob(node);
			
			ldb.set("success", true);
			ldb.set("reason", "任务成功启动");
			ldb.set("status", status);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		
		return AJAX;
	}
	
	@Action(value="refreshJob")
	public String refreshJob() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		try {
			int status = schedulerServiceClient.getJobStatus(node);
			
			Date endDate = schedulerServiceClient.getJobEndDate(node);
			if(endDate==null){
				ldb.set("endDate", "");
			}else{
				SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd H:m:s");
				String s = simpleDateFormat.format(endDate);
				ldb.set("endDate", s);
			}
			
			ldb.set("success", true);
			ldb.set("status", status);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		
		return AJAX;
	}
	
	@Action(value="againJob")
	public String againJob() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		
		try {
			RiseScheduler riseScheduler = (RiseScheduler) schedulerManager.getObject(RiseScheduler.class, node);
			
			RiseJob job = new RiseJob();
			job.setJobGuid(riseScheduler.getGuid());
			job.setUserGuid(riseScheduler.getUserGuid());
			job.setJobName(riseScheduler.getName());
			String jobType = riseScheduler.getJobType();
			job.setJobGroupName(jobType+"_JOBGROUP");
			job.setTriggerGroupName(jobType+"_TRIGGERGROUP");
			job.setJobType(jobType);
			
			byte[] b = riseScheduler.getJobData();
			JobDataMap jobDataMap = (JobDataMap) SerializableUtil.unSerialize(b);
			Map rjd = new HashMap();
			rjd.putAll(jobDataMap);
			job.setRjd(rjd);
			
			String serviceGuid = jobDataMap.getString(SchedulerConstant.SERVICEGUID);
			job.setServiceGuid(serviceGuid);
			
			String applicationGuid = jobDataMap.getString(SchedulerConstant.APPLICATIONGUID);
			if(applicationGuid!=null&&!applicationGuid.equals("")){
				job.setApplicationGuid(applicationGuid);
			}
			
			job.setCronExpression(riseScheduler.getCronExpression());
			job.setStartAtOnce(true);
			
			Date startDate = new Date();
			job.setStartDateTime(startDate);
			
			schedulerServiceClient.addJob(job);
			
			ldb.set("success", true);
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd H:m:s");
			String s = simpleDateFormat.format(startDate);
			ldb.set("startDate", s);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		
		return AJAX;
	}
	
	@Action(value="remove")
	public String remove() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		
		try {
//			假如运行中，则不能删除
			RiseScheduler riseScheduler = (RiseScheduler) schedulerManager.getObject(RiseScheduler.class, node);
			
			int status = riseScheduler.getStatus();
			if(status == RiseScheduler.STATUS_RUNNING){
				ldb.set("success", false);
				ldb.set("reason", "该任务已经处于运行状态，不能被删除。\n\r请刷新一下");
				
				this.json = JSONObject.fromObject(ldb).toString();
				return AJAX;
			}
			
			schedulerServiceClient.deleteJob(node);
			
			ldb.set("success", true);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		
		return AJAX;
	}
	
	@Action(value="viewDetail",
			results={@Result(name="success", location="/admin/scheduler/viewdetail.jsp")}
	)
	public String viewDetail() throws Exception {
		RiseScheduler riseScheduler = (RiseScheduler) schedulerManager.getObject(RiseScheduler.class, node);
		
		String detailContent = riseScheduler.getDetailContent();
		if(detailContent!=null&&!detailContent.equals(""))
			detailValue = detailContent.replaceAll("\"", "“");
		else
			detailValue = "";
		
		return SUCCESS;
	}
	
	@Action(value="removeDetail")
	public String removeDetail() throws Exception {
		LazyDynaBean ldb = new  LazyDynaBean();
		
		try {
			RiseScheduler riseScheduler = (RiseScheduler) schedulerManager.getObject(RiseScheduler.class, node);
			riseScheduler.setDetailContent(null);
			schedulerManager.saveObject(riseScheduler);
			
			ldb.set("success", true);
		} catch (Exception e) {
			ldb.set("success", false);
			ldb.set("reason", "有错，错误的原因："+e.getMessage());
		}
		
		this.json = JSONObject.fromObject(ldb).toString();
		
		return AJAX;
	}
}
